{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 这么好用，那就试试呗\n",
    "任务要求:\n",
    "\n",
    "1.1s采集一次工业现场温度(这里我们用NXEZ扩展版的ds18b20代替)。\n",
    "\n",
    "2.将温度实时显示工业现场(这里我们用NXEZ扩展版的数码管)。\n",
    "\n",
    "3.将温度实时传递给远端控制器(这我们就不实现了，假设下)。\n",
    "\n",
    "4.将温度在本地进行实时存储(这我们就不实现了，假设下)。\n",
    "\n",
    "针对上述任务，通常做法创建1个进程，1s采集一次温度数据、本地存储和远程发送。但这里有个问题，本体存储和远程发送需要的时间是不确定的，特别是本地存储，将数据提交给操作系统过后，操作系统不会立即写会硬盘、要攒够一个扇区才启动真正的写(这叫写回方式——操作系统先缓存到内存中，然后，达到写硬盘的条件后，再启动硬盘写；相对的是写通方式——每次应用层提交的写操作，都直接写硬盘。写通的缺点就是特别慢)。在真正写硬盘时，应用层的写操作被阻塞，等待着写完成；所以这里的耗时是不确定的。\n",
    "\n",
    "改进方式:启动4个进程，\n",
    "\n",
    "(1)进程1完成1s的数据采集，并将数据发往相应的队列中；\n",
    "\n",
    "(2)进程2完成将从队列中取出的数据在工业现场显示(本地数码管显示)；\n",
    "\n",
    "(3)进程3完成将从队列中取出的数据发送到远端(这里就不模拟了)；\n",
    "\n",
    "(4)进程4完成从队列中取出的数据发送进行本地存储(这里就不模拟了)。\n",
    "\n",
    "这样改进是不是解决的执行时间不确定的问题，同时体会到操作系统的多任务让程序设计如此简洁、美丽吧。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from multiprocessing import Process, Queue\n",
    "import time\n",
    "import os\n",
    "from sakshat import SAKSHAT\n",
    "from sakspins import SAKSPins as PINS\n",
    "\n",
    "#Declare the SAKS Board\n",
    "SAKS = SAKSHAT()\n",
    "\n",
    "#ds18b20采集进程\n",
    "def get_ds18b20(task_name, mult_queue1, mult_queue2, mult_queue3):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            #从 ds18b20 读取温度（摄氏度为单位）\n",
    "            temp = SAKS.ds18b20.temperature\n",
    "            \n",
    "            #返回值为 -128.0 表示读取失败\n",
    "            if temp == -128.0 :\n",
    "                #本次采集不进行处理\n",
    "                continue\n",
    "                \n",
    "            #将采集到的温度发送至本地显示进程\n",
    "            mult_queue1.put(temp)      \n",
    "            \n",
    "            #将采集到的温度发送至远程发送进程\n",
    "            mult_queue2.put(temp)   \n",
    "            \n",
    "            #将采集到的温度发送至本地存储进程\n",
    "            mult_queue3.put(temp)  \n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#数码管显示温度进程\n",
    "def digital_display(task_name, mult_queue):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            #在本地进行温度值显示\n",
    "            SAKS.digital_display.show((\"%5.1f\" % mult_queue.get()).replace(' ','#'))\n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#发送给远端进程\n",
    "def send_remote(task_name, mult_queue):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            print (\"1.将温度值\" + (\"%5.1f\" % mult_queue.get()).replace(' ','#') + \"发送至远端\")\n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#消息本地存储进程\n",
    "def tmp_store(task_name, mult_queue):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            print (\"2.将温度值\" + (\"%5.1f\" % mult_queue.get()).replace(' ','#') + \"进程本地存储\")\n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        #定义本地显示、远程发送和本地存储的队列\n",
    "        disp_q = Queue()\n",
    "        remote_q = Queue()\n",
    "        store_q = Queue()\n",
    "        \n",
    "        #创建温度采集、本地显示温度、远程发送温度、本地温度存储进程\n",
    "        get_ds18b20_prog = Process(target=get_ds18b20, args=(\"温度采集进程\", disp_q, remote_q, store_q))\n",
    "        dig_disp_prog    = Process(target=digital_display, args=(\"本地温度显示进程\", disp_q))\n",
    "        send_remote_prog = Process(target=send_remote, args=(\"远程发送进程\", remote_q))\n",
    "        tmp_store_prog   = Process(target=tmp_store, args=(\"温度本地存储进程\", store_q))\n",
    "        \n",
    "        # 启动任务\n",
    "        get_ds18b20_prog.start()\n",
    "        dig_disp_prog.start()\n",
    "        send_remote_prog.start()\n",
    "        tmp_store_prog.start()\n",
    "\n",
    "        #等待启动的进程执行结束\n",
    "        get_ds18b20_prog.join()\n",
    "        dig_disp_prog.join()\n",
    "        send_remote_prog.join()\n",
    "        tmp_store_prog.join()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
